package com.evil.admin.handler;

import com.alibaba.fastjson.JSONException;
import com.evil.common.application.exception.ApplicationException;
import com.evil.common.core.entity.R;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.List;

@Slf4j
@RestControllerAdvice(basePackages = "com.evil.admin.controller")
public class WebGlobalExceptionHandler {

    @ResponseBody
    @ExceptionHandler({BusinessException.class, ApplicationException.class})
    public R<?> handleBusinessException(BusinessException exception) {
        log.error(exception.getMessage(), exception);
        return R.error(exception.getCode(), exception.getMessage(), exception.getData());
    }

    @ResponseBody
    @ExceptionHandler({ValidationException.class, ConstraintViolationException.class})
    public R<?> handleConstraintViolationException(ValidationException exception) {
        log.error(exception.getMessage(), exception);
        return R.error(RCodeEnum.ERROR_PARAMETER, exception.getMessage().split(": ")[1]);
    }

    @ResponseBody
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public R<?> handleValidateException(MethodArgumentNotValidException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        String errorMessage = fieldErrors.get(0).getDefaultMessage();
        log.error(errorMessage, exception);
        return R.error(RCodeEnum.ERROR_PARAMETER.getCode(), errorMessage);
    }

    @ResponseBody
    @ExceptionHandler({BindException.class})
    public R<?> handleBindException(BindException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        String errorMessage = fieldErrors.get(0).getDefaultMessage();
        log.error(errorMessage, exception);
        return R.error(RCodeEnum.ERROR_PARAMETER.getCode(), errorMessage);
    }

    @ResponseBody
    @ExceptionHandler({RuntimeException.class})
    public R<?> handleRuntimeException(RuntimeException exception) {
        log.error(exception.getMessage(), exception);
        if (null != exception.getCause()) {
            // TODO Debug To Modify Exception Type
//            if (exception.getCause() instanceof ClientException) {
//                log.error(exception.getMessage(), exception);
//                return R.error("服务器升级中，请稍后重试");
//            }
            if (exception.getCause() instanceof JSONException) {
                return R.error(RCodeEnum.ERROR_RUNTIME, exception.getMessage());
            }
        }
        return R.error(RCodeEnum.ERROR_RUNTIME);
    }

    @ResponseBody
    @ExceptionHandler({Exception.class})
    public R<?> handleException(Exception exception) {
        log.error(exception.getMessage(), exception);
        return R.error(exception.getMessage());
    }
}
